﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://wpfimageviewer.codeplex.com
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Windows.Threading;
using System.Collections.Specialized;
using DirectoryViewModels;
using System.Threading;
using BrainTechLLC.FileMaintenance;
using BrainTechLLC.WPF;
using DragDropLibrary;

using System.ComponentModel;
using BrainTechLLC.ThreadSafeObjects;
using System.Diagnostics;
using System.Collections.ObjectModel;

namespace BrainTechLLC.FolderExplorer
{
    public partial class FolderExplorerControl : UserControl
    {
        DispatcherTimer _searchTimer = new DispatcherTimer() { IsEnabled = true, Interval = new TimeSpan(0, 0, 0, 2, 500) };
        DispatcherTimer _tmrCheck = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 0, 1, 200), IsEnabled = true };
        DispatcherTimer _tmrPopulate = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 0, 0, 700), IsEnabled = true };
        DispatcherTimer _tmrCheckExpand = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 0, 0, 200), IsEnabled = true };
        ThreadSafeQueue<FolderViewModel> _Queue = new ThreadSafeQueue<FolderViewModel>();
        public static int MaxRecursiveSubdirCount = 100;
        public int _timerPopulateCount;

        private void StartTimers()
        {
            _tmrCheck.Tick += new EventHandler(_tmrCheck_Tick);
            _tmrCheck.Start();
            _tmrCheckExpand.Tick += new EventHandler(_tmrCheckExpand_Tick);
            _tmrCheckExpand.Start();
            _searchTimer.Tick += new EventHandler(_searchTimer_Tick);
            _searchTimer.Start();
            _tmrPopulate.Tick += new EventHandler(_tmrPopulate_Tick);
            _tmrPopulate.Start();
            ThreadStart ts = new ThreadStart(Worker);
            Thread t = new Thread(ts) { IsBackground = true, Priority = ThreadPriority.Normal };
            t.Start();
        }

        void Worker()
        {
            while (true)
            {
                while (_Queue.Count == 0)
                {
                    Thread.Sleep(60);
                }
                FolderViewModel dequeued = _Queue.DequeueItem();

                while (dequeued != null)
                {
                    dequeued.ReadFoldersOnDemand(int.MaxValue, ref dequeued._subFoldersForUIBinding, ref dequeued._subFolderList);
                    dequeued = _Queue.DequeueItem();
                }
            }
        }

        void _tmrPopulate_Tick(object sender, EventArgs e)
        {
            _tmrPopulate.Stop();

            _timerPopulateCount++;

            if (_timerPopulateCount % 4 == 3)
            {
                RootFolder.GetAllFoldersInMemory().ForEach(f =>
                {
                    if (f.TotalFileCountDirty)
                    {
                        f.RaisePropertyChanged("TotalFileCount");
                    }
                    if (f.TotalSubdirCountDirty)
                    {
                        f.RaisePropertyChanged("RecursiveSubDirectoryCount");
                    }
                });
            }

            if (!NoSizes && _Queue.Count < 1000)
            {
                List<FolderViewModel> results = new List<FolderViewModel>();
                List<FolderViewModel> readyForSizing = new List<FolderViewModel>();
                List<FolderViewModel> complete = new List<FolderViewModel>();
                for (int pass = 0; pass < 3; pass++)
                {
                    for (int n = 0; n < RootFolder.SubFolders.Count; n++)
                    {
                        var fold = RootFolder.SubFolders[n];
                        if (!fold.Complete)
                        {
                            if (pass == 0 && fold.RecursiveSubDirectoryCount > 100)
                            {
                                continue;
                            }
                            else if (pass == 1 && fold.RecursiveSubDirectoryCount > 500)
                            {
                                continue;
                            }
                            fold.FindFoldersWithoutCachedSubfolders(results, complete, 600);
                        }
                        else
                        {
                            if (!NoSizes && fold._CorrectDirectorySize == false && !fold._calculatingDirectorySize && !fold._abortCalcDirSize)
                            {
                                readyForSizing.Add(fold);
                            }
                        }
                    }
                }

                if (FolderViewModel.CurrentAsyncResizes.Count < 3 && readyForSizing.Count > 0)
                {
                    if (results.Count == 0)
                    {
                        MaxRecursiveSubdirCount += 100;
                    }
                    else
                    {
                        MaxRecursiveSubdirCount = Math.Max(100, MaxRecursiveSubdirCount - 100);
                    }

                    if (_Queue.Count > 0)
                    {
                        MaxRecursiveSubdirCount = Math.Max(100, MaxRecursiveSubdirCount - 20);
                    }
                    else
                    {
                        MaxRecursiveSubdirCount += 2;
                    }

                    if (readyForSizing.Count > 6)
                    {
                        MaxRecursiveSubdirCount += 200;
                    }

                    int maxToSize = 2;
                    int sized = 0;
                    readyForSizing.Sort(new Comparison<FolderViewModel>((f1, f2) => f1.RecursiveSubDirectoryCount.CompareTo(f2.RecursiveSubDirectoryCount)));

                    for (int n = 0; n < readyForSizing.Count && sized < maxToSize; n++)
                    {
                        var fvm = readyForSizing[n];
                        if (fvm.RecursiveSubDirectoryCount > MaxRecursiveSubdirCount || NoSizes)
                        {
                            continue;
                        }
                        fvm.CalcDirSizeAsync();
                        sized++;
                    }
                }

                if (!NoSizes && _Queue.Count < 1000)
                {
                    _Queue.EnqueueMultiple(results);
                }
            }

            _tmrPopulate.Start();
        }

        void _tmrCheckExpand_Tick(object sender, EventArgs e)
        {
            _tmrCheckExpand.Stop();

            if (_loading)
            {
                _loading = false;
            }
            else
            {
                if (AddedNew.Count > 0)
                {
                    SizeBorder(border, AddedNew);
                    AddedNew.Clear();
                    _needsRecalcVisible = true;
                }
            }

            _tmrCheckExpand.Start();
        }

        void _searchTimer_Tick(object sender, EventArgs e)
        {
            if (_searchTextChanged)
            {
                _searchTimer.Stop();

                _searchTextChanged = false;
                DoSearch(null);

                _searchTimer.Start();
            }
        }


        void _tmrCheck_Tick(object sender, EventArgs e)
        {
            DispatcherTimer tmr = sender as DispatcherTimer;
            tmr.Stop();
            int vis = 0;
            int nonvis = 0;

            if (_needsRecalcVisible)
            {
                _needsRecalcVisible = false;

                if (_TreeViewItems != null && _TreeViewItems.Count > 0)
                {                    
                    double maxHeight = treeView1.ActualHeight;
                    for (int n = 0; n < _TreeViewItems.Count; n++)
                    {
                        TreeViewItem tvi = _TreeViewItems[n];
                        FolderViewModel f = tvi.Tag as FolderViewModel;
                        try
                        {
                            GeneralTransform gt = (tvi as Visual).TransformToVisual(treeView1);
                            var p = gt.Transform(new System.Windows.Point(0, 0));
                            if (p.Y < 0D || p.Y > maxHeight)
                            {
                                //if (sawVisible)
                                //{
                                //    for (int i = n; i < _TreeViewItems.Count; i++)
                                //    {
                                //        f = _TreeViewItems[i].Tag as FolderViewModel;
                                //        f.IsVisible = false;
                                //        nonvis++;
                                //    }
                                //    break;
                                //}

                                f.IsVisible = false;
                                nonvis++;
                            }
                            else
                            {                                
                                f.IsVisible = true;
                                vis++;
                            }
                        }
                        catch // (Exception ex)
                        {
                            //Thread.Sleep(20);
                            // Console.WriteLine(ex.ToString());
                            break;
                        }
                    }
                }
            }

            // Console.WriteLine(string.Format("{0} / {1}", vis, nonvis));
            tmr.Start();
        }

        void tmr_Tick(object sender, EventArgs e)
        {
            DispatcherTimer tmr = sender as DispatcherTimer;
            tmr.Stop();
            tmr.Tick -= tmr_Tick;
            tmr.IsEnabled = false;

            var pos = Mouse.GetPosition(this);
            if (_lastPos.X == pos.X && _lastPos.Y == pos.Y)
            {
                // TODO: HEREHERE
                // PutFolderInEditMode(_lastFolder);
            }
            else
            {
                _lastPos = new Point(-1, -1);
                _lastFolder = null;
            }
        }
    }
}
